package com.ny.zmb.openapi.controller;

import com.alibaba.fastjson.JSONObject;
import com.ny.zmb.openapi.config.YsConfig;
import com.ny.zmb.openapi.util.*;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@CrossOrigin
@RestController
@RequestMapping("recharge")
public class RechargeController {

    @Resource
    private YsUtil ycutil;

    /**
     * 商户端私钥证书
     * 生产环境需要使用自己生产的私钥证书
     */
    private String YS_PUBLIC_CER_PATH = new YsConfig().getYsPublicCerPath();


    /**
     * 请求地址域名
     */
    private static final String HTTP_NET = "https://appdev.ysepay.com";

    /**
     * 线上充值
     */
    @GetMapping("portalRecharge")
    public JSONObject portalRecharge(String mobile, String rechargeAmount, String mercId) throws Exception {
        String httpUrl = HTTP_NET + "/openapi/prepose/portalRecharge";
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("mobile", mobile);
        dataMap.put("rechargeAmount", rechargeAmount);
        Map<String, String> reqMap = ycutil.resultMap("mercId", mercId, dataMap, "prepose.portalRecharge");
        String key = reqMap.get("resultKey");
        reqMap.remove("resultKey");
        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(httpUrl, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("查询失败");
                }
            } else {
                System.out.println("验签失败,未返回加签信息,可能是未配置发起方或者未配置发起方的证书类型,返回结果提示为:{}" + resMap.get("msg"));
                throw new Exception("查询失败");
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/
            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                String s = new String(data, "UTF-8");
                resMap.put("businessData", s);
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
                return JSONObject.parseObject(s);
            }
            throw new Exception("查询失败");
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("查询失败");
        }
    }


    /**
     * 线下汇款充值
     */
    @GetMapping("bind")
    public JSONObject bind(String reqMsgId, String userCode, String bankaccountNo,String banktype,String bankaddrNo,String bankaccountType,String openBankname) throws Exception {
        String httpUrl = HTTP_NET + "/openapi/prepose/settlementAccount/bind";
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("reqMsgId", reqMsgId);
        dataMap.put("userCode", userCode);
        dataMap.put("bankaccountNo", bankaccountNo);
        dataMap.put("banktype", banktype);
        dataMap.put("bankaddrNo", bankaddrNo);
        dataMap.put("bankaccountType", bankaccountType);
        dataMap.put("openBankname", openBankname);
        Map<String, String> reqMap = ycutil.resultMap("reqMsgId", reqMsgId, dataMap, "prepose.settlementAccount.bind");
        String key = reqMap.get("resultKey");
        reqMap.remove("resultKey");
        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(httpUrl, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("查询失败");
                }
            } else {
                System.out.println("验签失败,未返回加签信息,可能是未配置发起方或者未配置发起方的证书类型,返回结果提示为:{}" + resMap.get("msg"));
                throw new Exception("查询失败");
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/
            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                String s = new String(data, "UTF-8");
                resMap.put("businessData", s);
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
                return JSONObject.parseObject(s);
            }
            throw new Exception("查询失败");
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("查询失败");
        }
    }
}